package com.flca.pstc42.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;

import com.flca.pstc42.dto.AdresDto;
import com.flca.pstc42.dto.DistanceDto;

class CalcTravelDistanceHelper {

	private final static String ENCODING = "UTF-8";
	private final static String KEY = "ABQIAAAAss0AqADv9T6pqHLm5mXsoBSBG7ar0SUIHfiWpVc1cPjoIw4TChRLhdRSKUN9AKdnH93wnhkHxDaarw";

	static void getTravelDistance(DistanceDto aResult) 
	{
		AdresDto aFrom = aResult.getFromAdres();
		AdresDto aTo = aResult.getToAdres();
		
		BufferedReader in;
		try {
			in = new BufferedReader(new InputStreamReader(new URL(
					"http://maps.google.com/maps/nav?q="
							+ URLEncoder.encode(makeQuery(aFrom, aTo), ENCODING)
							+ "&output=csv&key=" + KEY).openStream()));

			String line;
			int statusCode = -1;
			line = in.readLine();
			if (line != null) {
//				Format: {"name":"from: Nuenen to: Amsterdam","Status":{"code":200,"request":"directions"},"Placemark":[{"id":"","address":"Nuenen, The Netherlands","AddressDetails":{"Country":{"CountryNameCode":"NL","AdministrativeArea":{"AdministrativeAreaName":"Noord-Brabant","Locality":{"LocalityName":"Nuenen"}}},"Accuracy": 4},"Point":{"coordinates":[5.547561,51.473752,0]}},{"id":"","address":"Amsterdam, The Netherlands","AddressDetails":{"Country":{"CountryNameCode":"NL","AdministrativeArea":{"AdministrativeAreaName":"Noord-Holland","Locality":{"LocalityName":"Amsterdam"}}},"Accuracy": 4},"Point":{"coordinates":[4.890935,52.373801,0]}}],"Directions":{"copyrightsHtml":"Map data \u0026#169;2009 Tele Atlas ","summaryHtml":"126\u0026nbsp;km (about 1 hour 27 mins)","Distance":{"meters":125824,"html":"126\u0026nbsp;km"},"Duration":{"seconds":5230,"html":"1 hour 27 mins"},"Routes":[{"Distance":{"meters":125824,"html":"126\u0026nbsp;km"},"Duration":{"seconds":5230,"html":"1 hour 27 mins"},"summaryHtml":"126\u0026nbsp;km (about 1 hour 27 mins)","Steps":[{"descriptionHtml":"Head \u003Cb\u003Enorthwest\u003C\/b\u003E on \u003Cb\u003EBoordseweg\u003C\/b\u003E toward \u003Cb\u003EDe Smidse\u003C\/b\u003E","Distance":{"meters":1003,"html":"1.0\u0026nbsp;km"},"Duration":{"seconds":154,"html":"2 mins"},"Point":{"coordinates":[5.547560,51.473750,0]}},{"descriptionHtml":"\u003Cb\u003EBoordseweg\u003C\/b\u003E turns slightly \u003Cb\u003Eleft\u003C\/b\u003E and becomes \u003Cb\u003EPanakkers\u003C\/b\u003E","Distance":{"meters":341,"html":"0.3\u0026nbsp;km"},"Duration":{"seconds":37,"html":"37 secs"},"Point":{"coordinates":[5.534030,51.471470,0]}},{"descriptionHtml":"At the roundabout, take the \u003Cb\u003E1st\u003C\/b\u003E exit onto \u003Cb\u003EEuropalaan\u003C\/b\u003E","Distance":{"meters":1675,"html":"1.7\u0026nbsp;km"},"Duration":{"seconds":114,"html":"1 min"},"Point":{"coordinates":[5.535350,51.468570,0]}},{"descriptionHtml":"Continue on \u003Cb\u003ESterrenlaan\u003C\/b\u003E","Distance":{"meters":1666,"html":"1.7\u0026nbsp;km"},"Duration":{"seconds":126,"html":"2 mins"},"Point":{"coordinates":[5.511540,51.467490,0]}},{"descriptionHtml":"Turn \u003Cb\u003Eright\u003C\/b\u003E to merge onto \u003Cb\u003EN265\u003C\/b\u003E toward \u003Cb\u003E's-Hertogen-bosch\/\u003Cwbr\/\u003ESon en Breugel\/\u003Cwbr\/\u003ETilburg\u003C\/b\u003E","Distance":{"meters":1551,"html":"1.6\u0026nbsp;km"},"Duration":{"seconds":134,"html":"2 mins"},"Point":{"coordinates":[5.487620,51.467690,0]}},{"descriptionHtml":"Continue on \u003Cb\u003EJohn F Kennedylaan\u003C\/b\u003E (signs for \u003Cb\u003E's-Hertogenboschs\/\u003Cwbr\/\u003ENijmegen\/\u003Cwbr\/\u003ESon en Breugel\/\u003Cwbr\/\u003ETilburg\u003C\/b\u003E)","Distance":{"meters":1777,"html":"1.8\u0026nbsp;km"},"Duration":{"seconds":98,"html":"1 min"},"Point":{"coordinates":[5.489660,51.481560,0]}},{"descriptionHtml":"Turn \u003Cb\u003Eleft\u003C\/b\u003E at \u003Cb\u003EA58\u003C\/b\u003E","Distance":{"meters":2720,"html":"2.7\u0026nbsp;km"},"Duration":{"seconds":98,"html":"1 min"},"Point":{"coordinates":[5.480180,51.495980,0]}},{"descriptionHtml":"Take the exit onto \u003Cb\u003EA2\/\u003Cwbr\/\u003EE25\u003C\/b\u003E toward \u003Cb\u003EBest\/\u003Cwbr\/\u003E's-Hertogen-bosch\/\u003Cwbr\/\u003EAmsterdam\u003C\/b\u003E \u003Cdiv class=\"\"\u003EContinue to follow A2\u003C\/div\u003E","Distance":{"meters":108840,"html":"109\u0026nbsp;km"},"Duration":{"seconds":3728,"html":"1 hour 2 mins"},"Point":{"coordinates":[5.441720,51.493660,0]}},{"descriptionHtml":"Continue on \u003Cb\u003Es110\u003C\/b\u003E","Distance":{"meters":376,"html":"0.4\u0026nbsp;km"},"Duration":{"seconds":30,"html":"30 secs"},"Point":{"coordinates":[4.911230,52.337220,0]}},{"descriptionHtml":"Slight \u003Cb\u003Eright\u003C\/b\u003E at \u003Cb\u003ENieuwe Utrechtseweg\/\u003Cwbr\/\u003Es110\u003C\/b\u003E \u003Cdiv class=\"\"\u003EContinue to follow s110\u003C\/div\u003E","Distance":{"meters":988,"html":"1.0\u0026nbsp;km"},"Duration":{"seconds":108,"html":"1 min"},"Point":{"coordinates":[4.908080,52.340000,0]}},{"descriptionHtml":"Turn \u003Cb\
				statusCode = getStatusCode(line);
				aResult.setGoogleStatus(statusCode);
				if (statusCode == 200) {
					aResult.setTravelDistance(getDistance(line));
					aResult.setGoogleResult(line);
				}
			}
			
			fillStatusMsg(aResult, statusCode);
		} catch (Exception e) {
			aResult.setGoogleStatus(-1);
			aResult.setStatusMsg(e.getMessage());
		}

	}

	private static void fillStatusMsg(DistanceDto aResult, int statusCode) {
		switch (statusCode) {
			case 200 :
				aResult.setStatusMsg("ok");
			case 400:
				aResult.setStatusMsg("Bad Request");
			case 500:
				aResult.setStatusMsg("Unknown error from Google Encoder");
			case 601:
				aResult.setStatusMsg("Missing query");
			case 602:
				aResult.setStatusMsg("Addres not mapped yet");
			case 603:
				aResult.setStatusMsg("Legal problem");
			case 604:
				aResult.setStatusMsg("No route");
			case 610:
				aResult.setStatusMsg("Bad key");
			case 620:
				aResult.setStatusMsg("Too many queries");
			case -1 :
				aResult.setStatusMsg("unknown status code");
		}
	}

	private static String makeQuery(AdresDto aFrom, AdresDto aTo)
	{
		return "from: " + aFrom.getPcNum() + aFrom.getPcAlfa() + 
			" to: " + aTo.getPcNum() + aTo.getPcAlfa(); 
	}
	
	private static final String Q = "\"";
	private static final String STATUSCODE = "Status" + Q + ":{" + Q + "code" + Q + ":";
	// Format: {"name":"from: Nuenen to: Amsterdam","Status":{"code":200,"req...

	private static int getStatusCode(String aLine)
	{
		int x = aLine.indexOf(STATUSCODE);
		if (x > 0) {
			String substr = aLine.substring(x + STATUSCODE.length());
			String code = substr.substring(0, substr.indexOf(","));
			return Integer.parseInt(code); 
		} else {
			return -1;
		}
	}

	private static final String DIST = "Distance" + Q + ":{" + Q + "meters" + Q + ":";

	private static double getDistance(String aLine)
	{
		int x = aLine.indexOf(DIST);
		if (x > 0) {
			String substr = aLine.substring(x + DIST.length());
			String metersStr = substr.substring(0, substr.indexOf(","));
			int meters = Integer.parseInt(metersStr); 
			return meters / 1000.0;
		} else {
			return 0.0;
		}
	}
}
